/******************************************************************************
 * Copyright 2015 The Robotics Group, The Maersk Mc-Kinney Moller Institute,
 * Faculty of Engineering, University of Southern Denmark
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

#include "SimulatorLogEntryWidget.hpp"
#include "BodyMotionWidget.hpp"
#include "CollisionResultWidget.hpp"
#include "ConstraintWidget.hpp"
#include "ContactSetWidget.hpp"
#include "ContactVelocitiesWidget.hpp"
#include "DistanceResultWidget.hpp"
#include "DistanceMultiResultWidget.hpp"
#include "EquationSystemWidget.hpp"
#include "ForceTorqueWidget.hpp"
#include "LogMessageWidget.hpp"
#include "LogValuesWidget.hpp"

using namespace rw::core;
using namespace rwsim::log;
using namespace rwsimlibs::gui;

SimulatorLogEntryWidget::SimulatorLogEntryWidget(QWidget* parent):
	QWidget(parent),
	_properties(NULL)
{
}

SimulatorLogEntryWidget::~SimulatorLogEntryWidget()
{
}

void SimulatorLogEntryWidget::setProperties(PropertyMap::Ptr properties)
{
    _properties = properties;
}

SimulatorLogEntryWidget::Factory::Factory():
	        ExtensionPoint<SimulatorLogEntryWidget::Dispatcher>(
	                "rwsimlibs.gui.InternalInfoEntryWidget",
	                "InternalInfoEntryWidget extension point.")
	                {
	                }

std::list<SimulatorLogEntryWidget::Dispatcher::Ptr>
SimulatorLogEntryWidget::Factory::getWidgetDispatchers(
        const rw::core::Ptr<const SimulatorLog> entry)
{
    std::list<SimulatorLogEntryWidget::Dispatcher::Ptr> res;

    SimulatorLogEntryWidget::Dispatcher::Ptr dispatcher;
    dispatcher = ownedPtr(new BodyMotionWidget::Dispatcher());
    if (dispatcher->accepts(entry))
        res.push_back(dispatcher);
    dispatcher = ownedPtr(new CollisionResultWidget::Dispatcher());
    if (dispatcher->accepts(entry))
        res.push_back(dispatcher);
    dispatcher = ownedPtr(new ConstraintWidget::Dispatcher());
    if (dispatcher->accepts(entry))
        res.push_back(dispatcher);
    dispatcher = ownedPtr(new ForceTorqueWidget::Dispatcher());
    if (dispatcher->accepts(entry))
        res.push_back(dispatcher);
    dispatcher = ownedPtr(new ContactSetWidget::Dispatcher());
    if (dispatcher->accepts(entry))
        res.push_back(dispatcher);
    dispatcher = ownedPtr(new ContactVelocitiesWidget::Dispatcher());
    if (dispatcher->accepts(entry))
        res.push_back(dispatcher);
    dispatcher = ownedPtr(new DistanceResultWidget::Dispatcher());
    if (dispatcher->accepts(entry))
        res.push_back(dispatcher);
    dispatcher = ownedPtr(new DistanceMultiResultWidget::Dispatcher());
    if (dispatcher->accepts(entry))
        res.push_back(dispatcher);
    dispatcher = ownedPtr(new EquationSystemWidget::Dispatcher());
    if (dispatcher->accepts(entry))
        res.push_back(dispatcher);
    dispatcher = ownedPtr(new LogValuesWidget::Dispatcher());
    if (dispatcher->accepts(entry))
        res.push_back(dispatcher);
    dispatcher = ownedPtr(new LogMessageWidget::Dispatcher());
    if (dispatcher->accepts(entry))
        res.push_back(dispatcher);

    const SimulatorLogEntryWidget::Factory factory;
    const std::vector<Extension::Ptr> exts = factory.getExtensions();
    for(const Extension::Ptr ext : exts) {
        const SimulatorLogEntryWidget::Dispatcher::Ptr dispatcher =
                ext->getObject().cast<const SimulatorLogEntryWidget::Dispatcher>();
        if (!(dispatcher == NULL)) {
            if (dispatcher->accepts(entry))
                res.push_back(dispatcher);
        }
    }
    return res;
}

std::list<SimulatorLogEntryWidget*>
SimulatorLogEntryWidget::Factory::makeWidgets(
        const rw::core::Ptr<const SimulatorLog> entry,
        QWidget* parent)
{
    std::list<SimulatorLogEntryWidget*> res;
    const std::list<SimulatorLogEntryWidget::Dispatcher::Ptr> dispatchers =
            getWidgetDispatchers(entry);
    for(const SimulatorLogEntryWidget::Dispatcher::Ptr dispatcher : dispatchers)
    {
        res.push_back(dispatcher->makeWidget(entry,parent));
    }
    return res;
}
